package impl.sdi.persistence;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.sdi.model.User;
import com.sdi.persistence.UserDao;
import com.sdi.persistence.exception.AlreadyPersistedException;
import com.sdi.persistence.exception.NotPersistedException;
import com.sdi.persistence.exception.PersistenceException;


/**
 * Implementación de la interfaz de fachada al servicio de persistencia para
 * Alumnos. En este caso es Jdbc pero podría ser cualquier otra tecnologia 
 * de persistencia, por ejemplo, la que veremos más adelante JPA 
 * (mapeador de objetos a relacional)
 * 
 * @author alb
 *
 */
public class UserJdbcDao implements UserDao {

	public List<User> getUsers() {
		PreparedStatement ps = null;
		ResultSet rs = null;
		Connection con = null;
		
		List<User> users = new ArrayList<User>();

		try {
			// En una implemenntación más sofisticada estas constantes habría 
			// que sacarlas a un sistema de configuración: 
			// xml, properties, descriptores de despliege, etc 
			String SQL_DRV = "org.hsqldb.jdbcDriver";
			String SQL_URL = "jdbc:hsqldb:hsql://localhost";

			// Obtenemos la conexión a la base de datos.
			Class.forName(SQL_DRV);
			con = DriverManager.getConnection(SQL_URL, "sa", "");
			ps = con.prepareStatement("select * from user");
			rs = ps.executeQuery();

			while (rs.next()) {
				User user = new User();
				
				user.setNombre(rs.getString("NOMBRE"));
				user.setApellidos(rs.getString("APELLIDOS"));
				user.setEmail(rs.getString("EMAIL"));
				user.setIdUser(rs.getString("IDUSER"));
				user.setPassword(rs.getString("PASSWORD"));
				user.setActivada(rs.getInt("ACTIVADA"));
				
				users.add(user);
			}
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			throw new PersistenceException("Driver not found", e);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new PersistenceException("Invalid SQL or database schema", e);
		} finally  {
			if (rs != null) {try{ rs.close(); } catch (Exception ex){}};
			if (ps != null) {try{ ps.close(); } catch (Exception ex){}};
			if (con != null) {try{ con.close(); } catch (Exception ex){}};
		}
		
		return users;
	}

	@Override
	public void delete(User user) throws NotPersistedException {
		PreparedStatement ps = null;
		Connection con = null;
		int rows = 0;
		
		try {
			// En una implementación más sofisticada estas constantes habría 
			// que sacarlas a un sistema de configuración: 
			// xml, properties, descriptores de despliege, etc 
			String SQL_DRV = "org.hsqldb.jdbcDriver";
			String SQL_URL = "jdbc:hsqldb:hsql://localhost";

			// Obtenemos la conexión a la base de datos.
			Class.forName(SQL_DRV);
			con = DriverManager.getConnection(SQL_URL, "sa", "");
			ps = con.prepareStatement("delete from user where iduser = ?");
			
			ps.setString(1, user.getIdUser());

			rows = ps.executeUpdate();
			if (rows != 1) {
				throw new NotPersistedException("User " + user.getIdUser() + " not found");
			} 
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			throw new PersistenceException("Driver not found", e);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new PersistenceException("Invalid SQL or database schema", e);
		}
		finally  {
			if (ps != null) {try{ ps.close(); } catch (Exception ex){}};
			if (con != null) {try{ con.close(); } catch (Exception ex){}};
		}
	}

	@Override
	public User findByNick(String nick) {
		PreparedStatement ps = null;
		ResultSet rs = null;
		Connection con = null;
		User user = null;
		
		try {
			// En una implementación más sofisticada estas constantes habría 
			// que sacarlas a un sistema de configuración: 
			// xml, properties, descriptores de despliege, etc 
			String SQL_DRV = "org.hsqldb.jdbcDriver";
			String SQL_URL = "jdbc:hsqldb:hsql://localhost";

			// Obtenemos la conexión a la base de datos.
			Class.forName(SQL_DRV);
			con = DriverManager.getConnection(SQL_URL, "sa", "");
			ps = con.prepareStatement("select * from user where iduser = ?");
			ps.setString(1, nick);
			
			rs = ps.executeQuery();
			if (rs.next()) {
				user = new User();
				
				
				user.setNombre(rs.getString("NOMBRE"));
				user.setApellidos(rs.getString("APELLIDOS"));
				user.setEmail(rs.getString("EMAIL"));
				user.setIdUser(rs.getString("IDUSER"));
				user.setPassword(rs.getString("PASSWORD"));
				user.setActivada(rs.getInt("ACTIVADA"));
			}
			
		} catch (ClassNotFoundException e) {
			//e.printStackTrace();
			throw new PersistenceException("User not found", e);
		} catch (SQLException e) {
			//e.printStackTrace();
			throw new PersistenceException("Invalid SQL or database schema", e);
		}
		finally  {
			if (rs != null) {try{ rs.close(); } catch (Exception ex){}};
			if (ps != null) {try{ ps.close(); } catch (Exception ex){}};
			if (con != null) {try{ con.close(); } catch (Exception ex){}};
		}
		
		return user;
	}

	@Override
	public void save(User u) throws AlreadyPersistedException {
		PreparedStatement ps = null;
		Connection con = null;
		int rows = 0;
		
		try {
			// En una implementación más sofisticada estas constantes habría 
			// que sacarlas a un sistema de configuración: 
			// xml, properties, descriptores de despliege, etc 
			String SQL_DRV = "org.hsqldb.jdbcDriver";
			String SQL_URL = "jdbc:hsqldb:hsql://localhost";

			// Obtenemos la conexión a la base de datos.
			Class.forName(SQL_DRV);
			con = DriverManager.getConnection(SQL_URL, "sa", "");
			ps = con.prepareStatement(
					"insert into user (nombre, apellidos, iduser, email,password,activada) " +
					"values (?, ?, ?, ?,?,?)");
			
			ps.setString(1, u.getNombre());
			ps.setString(2, u.getApellidos());
			ps.setString(3, u.getIdUser());
			ps.setString(4, u.getEmail());
			ps.setString(5, u.getPassword());
			ps.setInt(6, u.getActivada());

			rows = ps.executeUpdate();
			if (rows != 1) {
				throw new AlreadyPersistedException("User " + u + " already persisted");
			} 

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			throw new PersistenceException("Driver not found", e);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new PersistenceException("Invalid SQL or database schema", e);
		}
		finally  {
			if (ps != null) {try{ ps.close(); } catch (Exception ex){}};
			if (con != null) {try{ con.close(); } catch (Exception ex){}};
		}
	}

	@Override
	public void update(User u) throws NotPersistedException {
		PreparedStatement ps = null;
		Connection con = null;
		int rows = 0;
		
		try {
			// En una implementación más sofisticada estas constantes habría 
			// que sacarlas a un sistema de configuración: 
			// xml, properties, descriptores de despliege, etc 
			String SQL_DRV = "org.hsqldb.jdbcDriver";
			String SQL_URL = "jdbc:hsqldb:hsql://localhost";

			// Obtenemos la conexión a la base de datos.
			Class.forName(SQL_DRV);
			con = DriverManager.getConnection(SQL_URL, "sa", "");
			ps = con.prepareStatement(
					"update user " +
					"set nombre = ?, apellidos = ?, email = ?,password = ?,activada = ? " +
					"where iduser = ?");
			
			ps.setString(1, u.getNombre());
			ps.setString(2, u.getApellidos());
			ps.setString(3, u.getEmail());
			ps.setString(4, u.getPassword());
			ps.setInt(5, u.getActivada());
			ps.setString(6, u.getIdUser());
			rows = ps.executeUpdate();
			if (rows != 1) {
				throw new NotPersistedException("User " + u + " not found");
			} 
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			throw new PersistenceException("Driver not found", e);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new PersistenceException("Invalid SQL or database schema", e);
		}
		finally  {
			if (ps != null) {try{ ps.close(); } catch (Exception ex){}};
			if (con != null) {try{ con.close(); } catch (Exception ex){}};
		}
	}

}
